home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / AlgoWaveTableObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  30.9 KB  |  1,023 lines  |  [TEXT/KAHL]

  1. /* AlgoWaveTableObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "AlgoWaveTableObject.h"
  31. #include "AlgoWaveTableList.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34. #include "CodeCenter.h"
  35. #include "PcodeStack.h"
  36. #include "PcodeSystem.h"
  37. #include "FixedPoint.h"
  38. #include "MainWindowStuff.h"
  39. #include "Alert.h"
  40. #include "Numbers.h"
  41. #include "AlgoWaveTableWindow.h"
  42. #include "WaveTableStorage.h"
  43. #include "CompilerRoot.h"
  44. #include "FunctionCode.h"
  45. #include "BufferedFileInput.h"
  46. #include "BufferedFileOutput.h"
  47.  
  48.  
  49. struct AlgoWaveTableObjectRec
  50.     {
  51.         MyBoolean                                DataModified;
  52.  
  53.         char*                                        Name;
  54.         char*                                        AlgoWaveTableFormula;
  55.  
  56.         MyBoolean                                NeedsToBeRebuilt;
  57.         WaveTableStorageRec*        WaveTableData; /* NIL if not built */
  58.         NumBitsType                            NumBits;
  59.         long                                        NumFrames;
  60.         long                                        NumTables;
  61.  
  62.         AlgoWaveTableWindowRec*    AlgoWaveTableWindow;
  63.  
  64.         struct CodeCenterRec*        CodeCenter;
  65.         struct MainWindowRec*        MainWindow;
  66.         AlgoWaveTableListRec*        AlgoWaveTableList;
  67.  
  68.         short                                        SavedWindowXLoc;
  69.         short                                        SavedWindowYLoc;
  70.         short                                        SavedWindowWidth;
  71.         short                                        SavedWindowHeight;
  72.     };
  73.  
  74.  
  75. /* allocate and create a new algorithmic wave table */
  76. AlgoWaveTableObjectRec*    NewAlgoWaveTableObject(struct CodeCenterRec* CodeCenter,
  77.                                                 struct MainWindowRec* MainWindow,
  78.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  79.     {
  80.         AlgoWaveTableObjectRec*    AlgoWaveTableObj;
  81.  
  82.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  83.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  84.         if (AlgoWaveTableObj == NIL)
  85.             {
  86.              FailurePoint1:
  87.                 return AlgoWaveTableObj;
  88.             }
  89.         AlgoWaveTableObj->Name = StringToBlockCopy("untitled");
  90.         if (AlgoWaveTableObj->Name == NIL)
  91.             {
  92.              FailurePoint2:
  93.                 ReleasePtr((char*)AlgoWaveTableObj);
  94.                 goto FailurePoint1;
  95.             }
  96.         AlgoWaveTableObj->AlgoWaveTableFormula = StringToBlockCopy(
  97.             "# frames : integer; tables : integer; data : fixedarray\x0a");
  98.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  99.             {
  100.              FailurePoint3:
  101.                 ReleasePtr(AlgoWaveTableObj->Name);
  102.                 goto FailurePoint2;
  103.             }
  104.         AlgoWaveTableObj->DataModified = False;
  105.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  106.         AlgoWaveTableObj->WaveTableData = NIL;
  107.         AlgoWaveTableObj->NumBits = eSample16bit;
  108.         AlgoWaveTableObj->NumFrames = 256;
  109.         AlgoWaveTableObj->NumTables = 256;
  110.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  111.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  112.         AlgoWaveTableObj->MainWindow = MainWindow;
  113.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  114.         AlgoWaveTableObj->SavedWindowXLoc = 0;
  115.         AlgoWaveTableObj->SavedWindowYLoc = 0;
  116.         AlgoWaveTableObj->SavedWindowWidth = 0;
  117.         AlgoWaveTableObj->SavedWindowHeight = 0;
  118.         return AlgoWaveTableObj;
  119.     }
  120.  
  121.  
  122. /* dispose of all data structures associated with wave table */
  123. void                                    DisposeAlgoWaveTableObject(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  124.     {
  125.         CheckPtrExistence(AlgoWaveTableObj);
  126.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  127.             {
  128.                 DisposeAlgoWaveTableWindow(AlgoWaveTableObj->AlgoWaveTableWindow);
  129.                 ERROR(AlgoWaveTableObj->AlgoWaveTableWindow != NIL,PRERR(ForceAbort,
  130.                     "DisposeAlgoWaveTableObject: window thing not NIL after disposing"));
  131.             }
  132.         ReleasePtr(AlgoWaveTableObj->Name);
  133.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  134.         if (AlgoWaveTableObj->WaveTableData != NIL)
  135.             {
  136.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  137.             }
  138.         ReleasePtr((char*)AlgoWaveTableObj);
  139.     }
  140.  
  141.  
  142. /* find out if any changes have been made to it */
  143. MyBoolean                            HasAlgoWaveTableObjectBeenModified(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  144.     {
  145.         CheckPtrExistence(AlgoWaveTableObj);
  146.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  147.             {
  148.                 return AlgoWaveTableObj->DataModified
  149.                     || HasAlgoWaveTableWindowBeenModified(AlgoWaveTableObj->AlgoWaveTableWindow);
  150.             }
  151.          else
  152.             {
  153.                 return AlgoWaveTableObj->DataModified;
  154.             }
  155.     }
  156.  
  157.  
  158. static FunctionParamRec        ArgList[] =
  159.     {
  160.         {"frames",eInteger},
  161.         {"tables",eInteger},
  162.         {"data",eArrayOfFixed}
  163.     };
  164. #define ARGLISTLENGTH (sizeof(ArgList) / sizeof(ArgList[0]))
  165.  
  166.  
  167. /* rebuild the wave table and return True if successful */
  168. MyBoolean                            AlgoWaveTableObjectBuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  169.     {
  170.         char*                                Blob;
  171.         PcodeRec*                        FuncCode;
  172.         CompileErrors                Error;
  173.         long                                LineNumber;
  174.         ParamStackRec*            ParamList;
  175.         EvalErrors                    OtherError;
  176.         OpcodeRec*                    ErrorOpcode;
  177.         long                                OffendingInstruction;
  178.         DataTypes                        ReturnType;
  179.         char*                                Buffer;
  180.         largefixedsigned*        Middle;
  181.         long                                Limit;
  182.         long                                Scan;
  183.         long                                NumberOfTablesInIt;
  184.         long                                TotalFrameCount;
  185.  
  186.  
  187.         CheckPtrExistence(AlgoWaveTableObj);
  188.  
  189.         /* make sure we are unbuilt */
  190.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  191.         ERROR(AlgoWaveTableObj->WaveTableData != NIL,PRERR(ForceAbort,
  192.             "AlgoWaveTableObjectBuild:  unbuilt object but it still exists"));
  193.  
  194.         /* bring the world up to date */
  195.         if (!MainWindowMakeUpToDateFunctions(AlgoWaveTableObj->MainWindow))
  196.             {
  197.                 return False;
  198.             }
  199.  
  200.         /* allocate the new wave table thing */
  201.         AlgoWaveTableObj->WaveTableData = NewWaveTableStorage(
  202.             AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj),
  203.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj));
  204.         if (AlgoWaveTableObj->WaveTableData == NIL)
  205.             {
  206.              FailurePointNegative1:
  207.                 AlertHalt("There is not enough memory available to compile the algorithmic "
  208.                     "wave table generator function.",NIL);
  209.             }
  210.         for (Scan = 0; Scan < AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj); Scan += 1)
  211.             {
  212.                 if (!WaveTableStorageAppendEntry(AlgoWaveTableObj->WaveTableData))
  213.                     {
  214.                      FailurePoint0:
  215.                         DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  216.                         goto FailurePointNegative1;
  217.                     }
  218.             }
  219.  
  220.         /* prepare the text blob to be evaluated */
  221.         Blob = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  222.         if (Blob == NIL)
  223.             {
  224.              FailurePoint1:
  225.                 goto FailurePoint0;
  226.             }
  227.  
  228.         /* perform compilation */
  229.         Error = CompileSpecialFunction(ArgList,ARGLISTLENGTH,&LineNumber,
  230.             &ReturnType,Blob,&FuncCode);
  231.         ReleasePtr(Blob);
  232.         /* show the error message if there is one */
  233.         if (Error != eCompileNoError)
  234.             {
  235.                 if (!AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj))
  236.                     {
  237.                         AlertHalt("A compile error occurred but there is not enough "
  238.                             "memory available to display the error message.",NIL);
  239.                         return False;
  240.                     }
  241.                 AlgoWaveTableWindowHiliteLine(AlgoWaveTableObj->AlgoWaveTableWindow,LineNumber - 1);
  242.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  243.                 return False;
  244.             }
  245.  
  246.         /* try to evaluate the code */
  247.         ParamList = NewParamStack();
  248.         if (ParamList == NIL)
  249.             {
  250.              SecondFailurePoint1:
  251.                 DisposePcode(FuncCode);
  252.                 AlertHalt("There is not enough memory available to evaluate the algorithmic "
  253.                     "wave table generator function.",NIL);
  254.                 return False;
  255.             }
  256.         /* add a space for the return value */
  257.         if (!AddIntegerToStack(ParamList,0))
  258.             {
  259.              SecondFailurePoint2:
  260.                 DisposeParamStack(ParamList);
  261.                 goto SecondFailurePoint1;
  262.             }
  263.         /* add the special parameters (SymbolStack order MUST be the same */
  264.         /* order as that used for the Parameterlist) */
  265.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  266.             {
  267.                 goto SecondFailurePoint2;
  268.             }
  269.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  270.             {
  271.                 goto SecondFailurePoint2;
  272.             }
  273.         Buffer = AllocPtrCanFail(AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)
  274.             * AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)
  275.             * sizeof(largefixedsigned),"degeneratesample");
  276.         if (Buffer == NIL)
  277.             {
  278.                 goto SecondFailurePoint2;
  279.             }
  280.         Limit = PtrSize(Buffer);
  281.         for (Scan = 0; Scan < Limit; Scan += 1)
  282.             {
  283.                 Buffer[Scan] = 0;
  284.             }
  285.         if (!AddArrayToStack(ParamList,Buffer))
  286.             {
  287.                 ReleasePtr(Buffer);
  288.                 goto SecondFailurePoint2;
  289.             }
  290.  
  291.         /* executing the actual code */
  292.         OtherError = EvaluatePcode(ParamList,FuncCode,
  293.             AlgoWaveTableObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,
  294.             AlgoWaveTableObj->MainWindow,
  295.             &MainWindowGetSampleLeftCopy,&MainWindowGetSampleRightCopy,
  296.             &MainWindowGetSampleMonoCopy,&MainWindowGetWaveTableFrameCount,
  297.             &MainWindowGetWaveTableTableCount,&MainWindowGetWaveTableArray);
  298.         DisposePcode(FuncCode);
  299.         if (OtherError != eEvalNoError)
  300.             {
  301.                 char*                    FuncNameString;
  302.                 FuncCodeRec*    ErrorFunction;
  303.                 MyBoolean            SuccessFlag;
  304.  
  305.                 /* present error message */
  306.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  307.                 SuccessFlag = False;
  308.                 ErrorFunction = GetFunctionFromOpcode(AlgoWaveTableObj->CodeCenter,ErrorOpcode);
  309.                 if (ErrorFunction == NIL)
  310.                     {
  311.                         FuncNameString = StringToBlockCopy("<anonymous>");
  312.                     }
  313.                  else
  314.                     {
  315.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  316.                     }
  317.                 if (FuncNameString != NIL)
  318.                     {
  319.                         char*                    Key;
  320.  
  321.                         Key = StringToBlockCopy("_");
  322.                         if (Key != NIL)
  323.                             {
  324.                                 char*                    BaseMessage;
  325.  
  326.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  327.                                 if (BaseMessage != NIL)
  328.                                     {
  329.                                         char*                    FixedMessage1;
  330.  
  331.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  332.                                         if (FixedMessage1 != NIL)
  333.                                             {
  334.                                                 char*                    NumberStr;
  335.  
  336.                                                 NumberStr = IntegerToString(OffendingInstruction);
  337.                                                 if (NumberStr != NIL)
  338.                                                     {
  339.                                                         char*                    FixedMessage2;
  340.  
  341.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  342.                                                         if (FixedMessage2 != NIL)
  343.                                                             {
  344.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  345.                                                                 SuccessFlag = True;
  346.                                                                 ReleasePtr(FixedMessage2);
  347.                                                             }
  348.                                                         ReleasePtr(NumberStr);
  349.                                                     }
  350.                                                 ReleasePtr(FixedMessage1);
  351.                                             }
  352.                                         ReleasePtr(BaseMessage);
  353.                                     }
  354.                                 ReleasePtr(Key);
  355.                             }
  356.                         ReleasePtr(FuncNameString);
  357.                     }
  358.                 if (!SuccessFlag)
  359.                     {
  360.                         AlertHalt("There is not enough memory available to show the "
  361.                             "compile error message.",NIL);
  362.                     }
  363.                 DisposeParamStack(ParamList);
  364.                 return False;
  365.             }
  366.  
  367.         /* add the new data */
  368.         Middle = (largefixedsigned*)GetStackArray(ParamList,3);
  369.         if (Middle == NIL)
  370.             {
  371.                 AlertHalt("NIL array returned from algorithmic wave table function.",NIL);
  372.              RebuildFailurePoint1:
  373.                 DisposeParamStack(ParamList);
  374.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  375.                 AlgoWaveTableObj->WaveTableData = NIL;
  376.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  377.                 return False;
  378.             }
  379.         ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
  380.             PRERR(ForceAbort,"AlgoWaveTableObjectBuild:  array alignment error"));
  381.         NumberOfTablesInIt = AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj);
  382.         TotalFrameCount = AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj);
  383.         if ((PtrSize((char*)Middle) / sizeof(largefixedsigned))
  384.             != NumberOfTablesInIt * TotalFrameCount)
  385.             {
  386.                 AlertHalt("Algorithmic wave table function returned array of wrong size.",NIL);
  387.              RebuildFailurePoint2:
  388.                 goto RebuildFailurePoint1;
  389.             }
  390.         for (Scan = 0; Scan < NumberOfTablesInIt; Scan += 1)
  391.             {
  392.                 long                                Index;
  393.  
  394.                 for (Index = 0; Index < TotalFrameCount; Index += 1)
  395.                     {
  396.                         WaveTableStorageSetFrame(AlgoWaveTableObj->WaveTableData,Scan,Index,
  397.                             Middle[(Scan * TotalFrameCount) + Index]);
  398.                     }
  399.             }
  400.         DisposeParamStack(ParamList);
  401.         AlgoWaveTableObj->NeedsToBeRebuilt = False;
  402.         return True;
  403.     }
  404.  
  405.  
  406. /* remove the wave table data */
  407. void                                    AlgoWaveTableObjectUnbuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  408.     {
  409.         CheckPtrExistence(AlgoWaveTableObj);
  410.         if (AlgoWaveTableObj->WaveTableData != NIL)
  411.             {
  412.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  413.                 AlgoWaveTableObj->WaveTableData = NIL;
  414.             }
  415.     }
  416.  
  417.  
  418. /* rebuild the wave table if it hasn't been built and return success flag */
  419. MyBoolean                            AlgoWaveTableObjectMakeUpToDate(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  420.     {
  421.         CheckPtrExistence(AlgoWaveTableObj);
  422.         if ((AlgoWaveTableObj->WaveTableData == NIL) || (AlgoWaveTableObj->NeedsToBeRebuilt)
  423.             || (AlgoWaveTableObj->AlgoWaveTableWindow != NIL))
  424.             {
  425.                 return AlgoWaveTableObjectBuild(AlgoWaveTableObj);
  426.             }
  427.          else
  428.             {
  429.                 return True;
  430.             }
  431.     }
  432.  
  433.  
  434. /* get a copy of the name of this object */
  435. char*                                    AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  436.     {
  437.         char*                                NameTemp;
  438.  
  439.         CheckPtrExistence(AlgoWaveTableObj);
  440.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  441.             {
  442.                 NameTemp = AlgoWaveTableWindowGetNameCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  443.             }
  444.          else
  445.             {
  446.                 NameTemp = CopyPtr(AlgoWaveTableObj->Name);
  447.             }
  448.         if (NameTemp != NIL)
  449.             {
  450.                 SetTag(NameTemp,"AlgoWaveTableNameCopy");
  451.             }
  452.         return NameTemp;
  453.     }
  454.  
  455.  
  456. /* install a new name on the object.  the object becomes owner of the name, so */
  457. /* the caller should not dispose of it. */
  458. void                                    AlgoWaveTableObjectNewName(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  459.                                                 char* Name)
  460.     {
  461.         CheckPtrExistence(AlgoWaveTableObj);
  462.         CheckPtrExistence(Name);
  463.         ReleasePtr(AlgoWaveTableObj->Name);
  464.         SetTag(Name,"AlgoWaveTableName");
  465.         AlgoWaveTableObj->Name = Name;
  466.         AlgoWaveTableObj->DataModified = True;
  467.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  468.         AlgoWaveTableListAlgoWaveTableNameChanged(AlgoWaveTableObj->AlgoWaveTableList,
  469.             AlgoWaveTableObj);
  470.     }
  471.  
  472.  
  473. /* get a copy of the formula that computes the algorithmic wave table */
  474. char*                                    AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  475.     {
  476.         char*                                TextCopy;
  477.  
  478.         CheckPtrExistence(AlgoWaveTableObj);
  479.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  480.             {
  481.                 TextCopy = AlgoWaveTableWindowGetFormulaCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  482.             }
  483.          else
  484.             {
  485.                 TextCopy = CopyPtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  486.             }
  487.         if (TextCopy != NIL)
  488.             {
  489.                 SetTag(TextCopy,"AlgoWaveTableFormulaCopy");
  490.             }
  491.         return TextCopy;
  492.     }
  493.  
  494.  
  495. /* install a new formula for the algorithmic wave table.  the object becomes the */
  496. /* owner of the memory block so the caller should not dispose of it. */
  497. void                                    AlgoWaveTableObjectNewFormula(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  498.                                                 char* Formula)
  499.     {
  500.         CheckPtrExistence(AlgoWaveTableObj);
  501.         CheckPtrExistence(Formula);
  502.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  503.         SetTag(Formula,"AlgoWaveTableFormula");
  504.         AlgoWaveTableObj->AlgoWaveTableFormula = Formula;
  505.         AlgoWaveTableObj->DataModified = True;
  506.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  507.     }
  508.  
  509.  
  510. /* find out how many bits are in each sample frame */
  511. NumBitsType                        AlgoWaveTableObjectGetNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  512.     {
  513.         CheckPtrExistence(AlgoWaveTableObj);
  514.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  515.             {
  516.                 return AlgoWaveTableWindowGetNumBits(AlgoWaveTableObj->AlgoWaveTableWindow);
  517.             }
  518.          else
  519.             {
  520.                 return AlgoWaveTableObj->NumBits;
  521.             }
  522.     }
  523.  
  524.  
  525. /* install a new number of bits in the object. */
  526. void                                    AlgoWaveTableObjectPutNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  527.                                                 NumBitsType NewNumBits)
  528.     {
  529.         CheckPtrExistence(AlgoWaveTableObj);
  530.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  531.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  532.             PRERR(ForceAbort,"AlgoWaveTableObjectPutNumBits:  bad value"));
  533.         AlgoWaveTableObj->NumBits = NewNumBits;
  534.         AlgoWaveTableObj->DataModified = True;
  535.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  536.     }
  537.  
  538.  
  539. /* find out how many frames there are per table */
  540. long                                    AlgoWaveTableObjectGetNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  541.     {
  542.         CheckPtrExistence(AlgoWaveTableObj);
  543.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  544.             {
  545.                 return AlgoWaveTableWindowGetNumTables(AlgoWaveTableObj->AlgoWaveTableWindow);
  546.             }
  547.          else
  548.             {
  549.                 return AlgoWaveTableObj->NumTables;
  550.             }
  551.     }
  552.  
  553.  
  554. /* set the number of tables in the wave table */
  555. void                                    AlgoWaveTableObjectPutNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  556.                                                 long NumTables)
  557.     {
  558.         CheckPtrExistence(AlgoWaveTableObj);
  559.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  560.         if (NumTables < 0)
  561.             {
  562.                 NumTables = 0;
  563.             }
  564.         AlgoWaveTableObj->NumTables = NumTables;
  565.         AlgoWaveTableObj->DataModified = True;
  566.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  567.     }
  568.  
  569.  
  570. /* get number of frames in each table */
  571. long                                    AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  572.     {
  573.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  574.             {
  575.                 return AlgoWaveTableWindowGetNumFrames(AlgoWaveTableObj->AlgoWaveTableWindow);
  576.             }
  577.          else
  578.             {
  579.                 return AlgoWaveTableObj->NumFrames;
  580.             }
  581.     }
  582.  
  583.  
  584. /* set the number of frames in each table */
  585. void                                    AlgoWaveTableObjectPutNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  586.                                                 long NumFrames)
  587.     {
  588.         CheckPtrExistence(AlgoWaveTableObj);
  589.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  590.         AlgoWaveTableObj->NumFrames = NumFrames;
  591.         AlgoWaveTableObj->DataModified = True;
  592.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  593.     }
  594.  
  595.  
  596. /* get a raw slice of data from the wave table.  if the wave table is modified, */
  597. /* this pointer becomes invalid. */
  598. char*                                    AlgoWaveTableObjectGetRawSlice(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  599.                                                 long AlgoWaveTableIndex)
  600.     {
  601.         CheckPtrExistence(AlgoWaveTableObj);
  602.         ERROR((AlgoWaveTableIndex < 0) || (AlgoWaveTableIndex
  603.             > AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)),PRERR(ForceAbort,
  604.             "AlgoWaveTableObjectGetRawSlice:  table index is out of range"));
  605.         return (char*)WaveTableStorageGetTable(AlgoWaveTableObj->WaveTableData,
  606.             AlgoWaveTableIndex);
  607.     }
  608.  
  609.  
  610. /* make the wave table open it's editor window */
  611. MyBoolean                            AlgoWaveTableObjectOpenWindow(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  612.     {
  613.         CheckPtrExistence(AlgoWaveTableObj);
  614.         if (AlgoWaveTableObj->AlgoWaveTableWindow == NIL)
  615.             {
  616.                 AlgoWaveTableObj->AlgoWaveTableWindow
  617.                     = NewAlgoWaveTableWindow(AlgoWaveTableObj->MainWindow,
  618.                     AlgoWaveTableObj,AlgoWaveTableObj->AlgoWaveTableList,
  619.                     AlgoWaveTableObj->SavedWindowXLoc,AlgoWaveTableObj->SavedWindowYLoc,
  620.                     AlgoWaveTableObj->SavedWindowWidth,AlgoWaveTableObj->SavedWindowHeight);
  621.             }
  622.          else
  623.             {
  624.                 AlgoWaveTableWindowBringToTop(AlgoWaveTableObj->AlgoWaveTableWindow);
  625.             }
  626.         return (AlgoWaveTableObj->AlgoWaveTableWindow != NIL);
  627.     }
  628.  
  629.  
  630. /* notify the object that the editor window is closing.  the object should */
  631. /* not take any action. */
  632. void                                    AlgoWaveTableObjectClosingWindowNotify(
  633.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  634.                                                 short NewX, short NewY, short NewWidth, short NewHeight)
  635.     {
  636.         CheckPtrExistence(AlgoWaveTableObj);
  637.         ERROR(AlgoWaveTableObj->AlgoWaveTableWindow == NIL,PRERR(ForceAbort,
  638.             "AlgoWaveTableObjectClosingWindowNotify:  window not open"));
  639.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  640.         AlgoWaveTableObj->SavedWindowXLoc = NewX;
  641.         AlgoWaveTableObj->SavedWindowYLoc = NewY;
  642.         AlgoWaveTableObj->SavedWindowWidth = NewWidth;
  643.         AlgoWaveTableObj->SavedWindowHeight = NewHeight;
  644.     }
  645.  
  646.  
  647. /* the document's name has changed, so we need to update the window */
  648. void                                    AlgoWaveTableObjectGlobalNameChange(AlgoWaveTableObjectRec*
  649.                                                 AlgoWaveTableObj, char* NewFilename)
  650.     {
  651.         CheckPtrExistence(AlgoWaveTableObj);
  652.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  653.             {
  654.                 AlgoWaveTableWindowGlobalNameChange(AlgoWaveTableObj->AlgoWaveTableWindow,
  655.                     NewFilename);
  656.             }
  657.     }
  658.  
  659.  
  660. /* Algorithmic Wave Table Object Subblock Format: */
  661. /*   1-byte format version number */
  662. /*       should be 1 */
  663. /*   2-byte little endian window X position (signed; origin at top-left corner) */
  664. /*   2-byte little endian window Y position */
  665. /*   2-byte little endian window width */
  666. /*   2-byte little endian window height */
  667. /*   4-byte little endian name length descriptor */
  668. /*   n-byte name string (line feed = 0x0a) */
  669. /*   4-byte little endian formula length descriptor */
  670. /*   n-byte formula string (line feed = 0x0a) */
  671. /*   4-byte little endian number of frames */
  672. /*       should be an integral power of 2 in the interval 2..65536 */
  673. /*   4-byte little endian number of tables */
  674. /*   1-byte number of bits */
  675. /*       should be either 8 or 16 */
  676.  
  677.  
  678. /* read in an object from the file. */
  679. FileLoadingErrors            AlgoWaveTableObjectNewFromFile(AlgoWaveTableObjectRec** ObjectOut,
  680.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  681.                                                 struct MainWindowRec* MainWindow,
  682.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  683.     {
  684.         AlgoWaveTableObjectRec*        AlgoWaveTableObj;
  685.         unsigned char                            UnsignedChar;
  686.         signed long                                SignedLong;
  687.         signed short                            SignedShort;
  688.         FileLoadingErrors                    Error;
  689.  
  690.         CheckPtrExistence(Input);
  691.         CheckPtrExistence(CodeCenter);
  692.         CheckPtrExistence(MainWindow);
  693.         CheckPtrExistence(AlgoWaveTableList);
  694.  
  695.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  696.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  697.         if (AlgoWaveTableObj == NIL)
  698.             {
  699.                 Error = eFileLoadOutOfMemory;
  700.              FailurePoint1:
  701.                 return Error;
  702.             }
  703.  
  704.         /*   1-byte format version number */
  705.         /*       should be 1 */
  706.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  707.             {
  708.                 Error = eFileLoadDiskError;
  709.              FailurePoint2:
  710.                 ReleasePtr((char*)AlgoWaveTableObj);
  711.                 goto FailurePoint1;
  712.             }
  713.         if (UnsignedChar != 1)
  714.             {
  715.                 Error = eFileLoadBadFormat;
  716.              FailurePoint3:
  717.                 goto FailurePoint2;
  718.             }
  719.  
  720.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  721.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  722.             {
  723.                 Error = eFileLoadDiskError;
  724.              FailurePoint4:
  725.                 goto FailurePoint3;
  726.             }
  727.         AlgoWaveTableObj->SavedWindowXLoc = SignedShort;
  728.  
  729.         /*   2-byte little endian window Y position */
  730.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  731.             {
  732.                 Error = eFileLoadDiskError;
  733.              FailurePoint5:
  734.                 goto FailurePoint4;
  735.             }
  736.         AlgoWaveTableObj->SavedWindowYLoc = SignedShort;
  737.  
  738.         /*   2-byte little endian window width */
  739.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  740.             {
  741.                 Error = eFileLoadDiskError;
  742.              FailurePoint6:
  743.                 goto FailurePoint5;
  744.             }
  745.         AlgoWaveTableObj->SavedWindowWidth = SignedShort;
  746.  
  747.         /*   2-byte little endian window height */
  748.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  749.             {
  750.                 Error = eFileLoadDiskError;
  751.              FailurePoint7:
  752.                 goto FailurePoint6;
  753.             }
  754.         AlgoWaveTableObj->SavedWindowHeight = SignedShort;
  755.  
  756.         /*   4-byte little endian name length descriptor */
  757.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  758.             {
  759.                 Error = eFileLoadDiskError;
  760.              FailurePoint8:
  761.                 goto FailurePoint7;
  762.             }
  763.         if (SignedLong < 0)
  764.             {
  765.                 Error = eFileLoadBadFormat;
  766.              FailurePoint9:
  767.                 goto FailurePoint8;
  768.             }
  769.  
  770.         /*   n-byte name string (line feed = 0x0a) */
  771.         AlgoWaveTableObj->Name = AllocPtrCanFail(SignedLong,"AlgoWaveTableObjectRec:  name");
  772.         if (AlgoWaveTableObj->Name == NIL)
  773.             {
  774.                 Error = eFileLoadOutOfMemory;
  775.              FailurePoint10:
  776.                 goto FailurePoint9;
  777.             }
  778.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->Name))
  779.             {
  780.                 Error = eFileLoadDiskError;
  781.              FailurePoint11:
  782.                 ReleasePtr(AlgoWaveTableObj->Name);
  783.                 goto FailurePoint10;
  784.             }
  785.  
  786.         /*   4-byte little endian formula length descriptor */
  787.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  788.             {
  789.                 Error = eFileLoadDiskError;
  790.              FailurePoint12:
  791.                 goto FailurePoint11;
  792.             }
  793.         if (SignedLong < 0)
  794.             {
  795.                 Error = eFileLoadBadFormat;
  796.              FailurePoint13:
  797.                 goto FailurePoint12;
  798.             }
  799.  
  800.         /*   n-byte formula string (line feed = 0x0a) */
  801.         AlgoWaveTableObj->AlgoWaveTableFormula = AllocPtrCanFail(SignedLong,
  802.             "AlgoWaveTableObjectRec:  formula");
  803.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  804.             {
  805.                 Error = eFileLoadOutOfMemory;
  806.              FailurePoint14:
  807.                 goto FailurePoint13;
  808.             }
  809.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->AlgoWaveTableFormula))
  810.             {
  811.                 Error = eFileLoadDiskError;
  812.              FailurePoint15:
  813.                 ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  814.                 goto FailurePoint14;
  815.             }
  816.  
  817.         /*   4-byte little endian number of frames */
  818.         /*       should be an integral power of 2 between 2 and 65536 */
  819.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  820.             {
  821.                 Error = eFileLoadDiskError;
  822.              FailurePoint16:
  823.                 goto FailurePoint15;
  824.             }
  825.         if ((SignedLong != 2) && (SignedLong != 4) && (SignedLong != 8)
  826.             && (SignedLong != 16) && (SignedLong != 32) && (SignedLong != 64)
  827.             && (SignedLong != 128) && (SignedLong != 256) && (SignedLong != 512)
  828.             && (SignedLong != 1024) && (SignedLong != 2048) && (SignedLong != 4096)
  829.             && (SignedLong != 8192) && (SignedLong != 16384) && (SignedLong != 32768)
  830.             && (SignedLong != 65536))
  831.             {
  832.                 Error = eFileLoadBadFormat;
  833.              FailurePoint17:
  834.                 goto FailurePoint16;
  835.             }
  836.         AlgoWaveTableObj->NumFrames = SignedLong;
  837.  
  838.         /*   4-byte little endian number of tables */
  839.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  840.             {
  841.                 Error = eFileLoadDiskError;
  842.              FailurePoint18:
  843.                 goto FailurePoint17;
  844.             }
  845.         if (SignedLong < 0)
  846.             {
  847.                 Error = eFileLoadBadFormat;
  848.              FailurePoint19:
  849.                 goto FailurePoint18;
  850.             }
  851.         AlgoWaveTableObj->NumTables = SignedLong;
  852.  
  853.         /*   1-byte number of bits */
  854.         /*       should be either 8 or 16 */
  855.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  856.             {
  857.                 Error = eFileLoadDiskError;
  858.              FailurePoint20:
  859.                 goto FailurePoint19;
  860.             }
  861.         if (UnsignedChar == 8)
  862.             {
  863.                 AlgoWaveTableObj->NumBits = eSample8bit;
  864.             }
  865.         else if (UnsignedChar == 16)
  866.             {
  867.                 AlgoWaveTableObj->NumBits = eSample16bit;
  868.             }
  869.         else
  870.             {
  871.                 Error = eFileLoadBadFormat;
  872.              FailurePoint21:
  873.                 goto FailurePoint20;
  874.             }
  875.  
  876.         /* fill in the other fields */
  877.         AlgoWaveTableObj->DataModified = False;
  878.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  879.         AlgoWaveTableObj->WaveTableData = NIL;
  880.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  881.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  882.         AlgoWaveTableObj->MainWindow = MainWindow;
  883.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  884.  
  885.         *ObjectOut = AlgoWaveTableObj;
  886.         return eFileLoadNoError;
  887.     }
  888.  
  889.  
  890. /* write the object out to the file. */
  891. FileLoadingErrors            AlgoWaveTableObjectWriteDataOut(
  892.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  893.                                                 struct BufferedOutputRec* Output)
  894.     {
  895.         char*                                StringTemp;
  896.  
  897.         CheckPtrExistence(AlgoWaveTableObj);
  898.         CheckPtrExistence(Output);
  899.  
  900.         /*   1-byte format version number */
  901.         /*       should be 1 */
  902.         if (!WriteBufferedUnsignedChar(Output,1))
  903.             {
  904.                 return eFileLoadDiskError;
  905.             }
  906.  
  907.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  908.         /* note that if the window is open when the file is saved, then the most recent */
  909.         /* coordinates of the window will not be used. */
  910.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowXLoc))
  911.             {
  912.                 return eFileLoadDiskError;
  913.             }
  914.  
  915.         /*   2-byte little endian window Y position */
  916.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowYLoc))
  917.             {
  918.                 return eFileLoadDiskError;
  919.             }
  920.  
  921.         /*   2-byte little endian window width */
  922.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowWidth))
  923.             {
  924.                 return eFileLoadDiskError;
  925.             }
  926.  
  927.         /*   2-byte little endian window height */
  928.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowHeight))
  929.             {
  930.                 return eFileLoadDiskError;
  931.             }
  932.  
  933.         /*   4-byte little endian name length descriptor */
  934.         StringTemp = AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObj);
  935.         if (StringTemp == NIL)
  936.             {
  937.                 return eFileLoadOutOfMemory;
  938.             }
  939.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  940.             {
  941.                 ReleasePtr(StringTemp);
  942.                 return eFileLoadDiskError;
  943.             }
  944.  
  945.         /*   n-byte name string (line feed = 0x0a) */
  946.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  947.             {
  948.                 ReleasePtr(StringTemp);
  949.                 return eFileLoadDiskError;
  950.             }
  951.         ReleasePtr(StringTemp);
  952.  
  953.         /*   4-byte little endian formula length descriptor */
  954.         StringTemp = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  955.         if (StringTemp == NIL)
  956.             {
  957.                 return eFileLoadOutOfMemory;
  958.             }
  959.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  960.             {
  961.                 ReleasePtr(StringTemp);
  962.                 return eFileLoadDiskError;
  963.             }
  964.  
  965.         /*   n-byte formula string (line feed = 0x0a) */
  966.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  967.             {
  968.                 ReleasePtr(StringTemp);
  969.                 return eFileLoadDiskError;
  970.             }
  971.         ReleasePtr(StringTemp);
  972.  
  973.         /*   4-byte little endian number of frames */
  974.         /*       should be an integral power of 2 between 2 and 65536 */
  975.         if (!WriteBufferedSignedLongLittleEndian(Output,
  976.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  977.             {
  978.                 return eFileLoadDiskError;
  979.             }
  980.  
  981.         /*   4-byte little endian number of tables */
  982.         if (!WriteBufferedSignedLongLittleEndian(Output,
  983.             AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  984.             {
  985.                 return eFileLoadDiskError;
  986.             }
  987.  
  988.         /*   1-byte number of bits */
  989.         /*       should be either 8 or 16 */
  990.         switch (AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj))
  991.             {
  992.                 default:
  993.                     EXECUTE(PRERR(ForceAbort,"AlgoWaveTableObjectWriteDataOut:  bad num bits"));
  994.                     break;
  995.                 case eSample8bit:
  996.                     if (!WriteBufferedUnsignedChar(Output,8))
  997.                         {
  998.                             return eFileLoadDiskError;
  999.                         }
  1000.                     break;
  1001.                 case eSample16bit:
  1002.                     if (!WriteBufferedUnsignedChar(Output,16))
  1003.                         {
  1004.                             return eFileLoadDiskError;
  1005.                         }
  1006.                     break;
  1007.             }
  1008.  
  1009.         return eFileLoadNoError;
  1010.     }
  1011.  
  1012.  
  1013. /* mark algorithmic wave table object as saved */
  1014. void                                    AlgoWaveTableObjectMarkAsSaved(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  1015.     {
  1016.         CheckPtrExistence(AlgoWaveTableObj);
  1017.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  1018.             {
  1019.                 AlgoWaveTableWindowWritebackModifiedData(AlgoWaveTableObj->AlgoWaveTableWindow);
  1020.             }
  1021.         AlgoWaveTableObj->DataModified = False;
  1022.     }
  1023.